package com.suxin.thread.future;

import java.util.concurrent.*;

/**
 * @author Tang
 * @classname SettableListenableFuture
 * @description [  ]
 * @date 2023/2/7 11:16
 */
public class SettableListenableFuture<T> implements ListenableFuture<T>{

    private final SettableTask<T> settableTask = new SettableTask<T>();

    private static final Callable<Object> DUMMY_CALLABLE = () -> {
        throw new RuntimeException("not support run!");
    };

    public boolean set(T v) {
        return settableTask.setValue(v);
    }

    public void setException(Throwable v) {
        settableTask.setExceptionResult(v);
    }

    @Override
    public void addCallback(ListenableFutureCallback<T> callback) {
        this.settableTask.addCallback(callback);
    }

    @Override
    public void addCallback(SuccessCallback<T> successCallback, FailureCallback failureCallback) {
        this.settableTask.addCallback(successCallback, failureCallback);
    }

    @Override
    public CompletableFuture<T> completable() {
        return this.settableTask.completable();
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return this.settableTask.cancel(mayInterruptIfRunning);
    }

    @Override
    public boolean isCancelled() {
        return this.settableTask.isCancelled();
    }

    @Override
    public boolean isDone() {
        return this.settableTask.isDone();
    }

    @Override
    public T get() throws InterruptedException, ExecutionException {
        return this.settableTask.get();
    }

    @Override
    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        return this.settableTask.get(timeout, unit);
    }

    /**
     * 扩展 ListenableFutureTask 增加 主动 完成 的功能
     * @param <T>
     */
    private static class SettableTask<T> extends ListenableFutureTask<T>{

        public SettableTask() {
            this((Callable<T>) DUMMY_CALLABLE);
        }

        private SettableTask(Callable<T> callable) {
            super(callable);
        }

        private SettableTask(Runnable runnable, T result) {
            super(runnable, result);
        }

        public boolean setValue(T v) {
            super.set(v);
            return true;
        }

        public void setExceptionResult(Throwable v) {
            super.setException(v);
        }
    }

}
